package graphUtility.test2;

import java.awt.Point;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.util.LinkedList;

import javax.xml.transform.TransformerConfigurationException;

import org.jgrapht.Graph;
import org.jgrapht.alg.DijkstraShortestPath;
import org.jgrapht.ext.GmlExporter;
import org.jgrapht.ext.GraphMLExporter;
import org.jgrapht.ext.VisioExporter;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.ListenableDirectedWeightedGraph;
import org.jgrapht.graph.SimpleGraph;
import org.jgrapht.graph.SimpleWeightedGraph;
import org.jgrapht.traverse.BreadthFirstIterator;
import org.xml.sax.SAXException;

import vacuumCleaner.Action;
import vacuumCleaner.Action.Type;
import vacuumCleaner.Agent;
import vacuumCleaner.Environment;
import vacuumCleaner.Floor;
import vacuumCleaner.Perception;
import vacuumCleaner.Square;

public class GraphFactory2 {

	private LinkedList<Action.Type> mossePossibili=new LinkedList<Action.Type>();
	private Graph<State2,DefaultEdge> simpleGraph;
	private Environment environment;
	private Perception myAgentPerception;
	private int countNode;
	private int countDirtySquares;
	
	State2 start;
	State2 finish;

	
	public GraphFactory2(Environment environment) {
		// TODO Auto-generated constructor stub
		simpleGraph=new ListenableDirectedWeightedGraph<State2, DefaultEdge>(DefaultEdge.class);
		this.environment=environment;
		int countNode=0;
		
	}
	public void initBuildGraph()
	{
		countDirtySquares=1;
		start=new State2("Start",new Point(environment.agent.x,environment.agent.y),countDirtySquares);
		simpleGraph.addVertex(start);
		generateNewGraph();
		
	}
	
	public Graph<State2, DefaultEdge> generateNewGraph()
	{
		
		System.out.println("Matt"+ countDirtySquares);
			if (countDirtySquares<=0)
					return simpleGraph;
		
		
		
			BreadthFirstIterator<State2, DefaultEdge> iterator=new BreadthFirstIterator<State2, DefaultEdge>(simpleGraph,start);
			
			
			while(iterator.hasNext() && countDirtySquares>0)
			{
				State2 currentRoot=iterator.next();
				
					if(!currentRoot.isVisited)
					{
						currentRoot.setVisited(true);
						//Provo a costruire percorso a nord
							if(canAddVertex(Type.NORTH,currentRoot))
							{
								State2 child=new State2("North",new Point(currentRoot.getAgentPosition().x-1,currentRoot.getAgentPosition().y),countDirtySquares);
								simpleGraph.addVertex(child);
								simpleGraph.addEdge(currentRoot, child);
							
							}
							if(canAddVertex(Type.SOUTH,currentRoot))
							{
								State2 child=new State2("South",new Point(currentRoot.getAgentPosition().x+1,currentRoot.getAgentPosition().y),countDirtySquares);
								simpleGraph.addVertex(child);
								simpleGraph.addEdge(currentRoot, child);
							
							}
							if(canAddVertex(Type.WEST,currentRoot))
							{
								State2 child=new State2("West",new Point(currentRoot.getAgentPosition().x,currentRoot.getAgentPosition().y-1),countDirtySquares);
								simpleGraph.addVertex(child);
								simpleGraph.addEdge(currentRoot, child);
							
							}
							if(canAddVertex(Type.EAST,currentRoot))
							{
								State2 child=new State2("East",new Point(currentRoot.getAgentPosition().x,currentRoot.getAgentPosition().y+1),countDirtySquares);
								simpleGraph.addVertex(child);
								simpleGraph.addEdge(currentRoot, child);
							
							}
							if(canAddVertex(Type.SUCK,currentRoot))
							{
								countDirtySquares--;
								System.out.println("STO SUCCHIANDO "+currentRoot.getAgentPosition().getX()+" "+currentRoot.getAgentPosition().getY());
								State2 child=new State2("Suck",new Point(currentRoot.getAgentPosition().x,currentRoot.getAgentPosition().y),countDirtySquares);
								simpleGraph.addVertex(child);
								simpleGraph.addEdge(currentRoot, child);
								
								
									if(countDirtySquares==0)
									{
										
										 finish=new State2("Finish",new Point(currentRoot.getAgentPosition().x,currentRoot.getAgentPosition().y),countDirtySquares);
										 simpleGraph.addVertex(finish);
										 simpleGraph.addEdge(child,finish);
									}
									
							
							}
					}
			}
			
			
			
		generateNewGraph();
		System.out.println("Mattonelle Sporche "+environment.floor.dirtySquares());
		return simpleGraph;
	}
	
	public void searchPath()
	{
		
		DijkstraShortestPath<State2, DefaultEdge> dij=new DijkstraShortestPath<State2, DefaultEdge>(simpleGraph, start, finish);
			
		for( DefaultEdge f :dij.getPathEdgeList())
			{
			int s=f.toString().indexOf(":");
			int end=f.toString().indexOf(")");
			String mossa=f.toString().substring(s+3, end);
			
					mossePossibili.add(StringToActionType(mossa));
					
			}
	}
	
	
	public Action.Type StringToActionType(String mossa)
	{
		if(mossa.equals("South"))
			return Action.Type.SOUTH;
		else if(mossa.equals("North"))
				return Action.Type.NORTH;
		else if(mossa.equals("West"))
				return Action.Type.WEST;
		else if(mossa.equals("East"))
			return Action.Type.EAST;
		else if(mossa.equals("Suck"))
			return Action.Type.SUCK;
		else
			return Action.Type.NOOP;
	}
	
	public State2 getStart() {
		return start;
	}

	public void setStart(State2 start) {
		this.start = start;
	}

	boolean canAddVertex(Type type,State2 currentRoot)
	{
		
	
			if(currentRoot.getAgentPosition().x>0 && type==Type.NORTH &&
				myAgentPerception.floor.get(currentRoot.getAgentPosition().x-1,currentRoot.getAgentPosition().y)!=Square.Type.OBSTACLE)
				return true;
			else if(currentRoot.getAgentPosition().x<myAgentPerception.floor.length-1 && type==Type.SOUTH &&
					myAgentPerception.floor.get(currentRoot.getAgentPosition().x+1,currentRoot.getAgentPosition().y)!=Square.Type.OBSTACLE)
				return true;
			else if(currentRoot.getAgentPosition().y>0 && type==Type.WEST &&
					myAgentPerception.floor.get(currentRoot.getAgentPosition().x,currentRoot.getAgentPosition().y-1)!=Square.Type.OBSTACLE)
				return true;
			else if(currentRoot.getAgentPosition().y<myAgentPerception.floor.width-1 && type==Type.EAST &&
					myAgentPerception.floor.get(currentRoot.getAgentPosition().x,currentRoot.getAgentPosition().y+1)!=Square.Type.OBSTACLE)
				return true;
			else if(myAgentPerception.floor.get(currentRoot.getAgentPosition().x,currentRoot.getAgentPosition().y)==Square.Type.DIRTY && type==Type.SUCK)
				return true;
				
		return false;
	
	}

	public Graph<State2, DefaultEdge> getSimpleGraph() {
		return simpleGraph;
	}

	public void setSimpleGraph(Graph<State2, DefaultEdge> simpleGraph) {
		this.simpleGraph = simpleGraph;
	}


	public LinkedList<Action.Type> getMossePossibili() {
		return mossePossibili;
	}


	public void setMossePossibili(LinkedList<Action.Type> mossePossibili) {
		this.mossePossibili = mossePossibili;
	}
	public Perception getMyPerception() {
		return myAgentPerception;
	}
	public void setMyPerception(Perception myAgentPerception) {
		this.myAgentPerception = myAgentPerception;
	}
	
	
}
